package com.rds.workflow.lifecycle;
import com.rds.common.core.domain.AjaxResult;
import com.rds.common.core.domain.entity.Document;
import com.rds.common.core.domain.entity.DynamicVo;
import com.rds.common.core.service.IDynamicService;
import com.rds.common.utils.DateUtils;
import com.rds.common.utils.StringUtils;
//import com.rds.system.common.LifecycleUtil;
//import com.rds.system.common.history.HistoryRecordUtil;
import com.rds.system.domain.RdaState;
import com.rds.system.service.*;
import com.rds.workflow.domain.RdaWorkflow;
import com.rds.workflow.domain.RdaWorkflowTemplete;
import com.rds.workflow.service.IRdaWorkflowService;
import com.rds.workflow.service.IRdaWorkflowTempleteService;

import java.util.*;

/**
 * 此类主要用作生命周期相关操作(单独给流程用)
 * @version : 1.0
 * @Copyright: Copyright(c) 2020-2021 All right reserved
 * @Company: GUANGZHOU RDS Co.,LTD
 * @author: LiChuanlong
 * @create Date : 2021/12/19 : 22:50
 */
public class WorkFlowLifeCycleUtil {
    private final IRdaStateService rdaStateService;

    /**历史记录持久化 2021-12-13**/
    private ISysHistoryService sysHistoryService;

    private IRdaWorkflowService workflowService;

    private IRdaWorkflowTempleteService workflowTempleteService;

//    private IDocumentService documentService;

    private IDynamicService dynamicService;




    public WorkFlowLifeCycleUtil(IRdaStateService  rdaStateService){
        this.rdaStateService = rdaStateService;
    }

    /*************************************** 历史记录写进数据库-持久化 2021-12-13 [begin] **********************************************************/
    public WorkFlowLifeCycleUtil(IRdaStateService  rdaStateService, IRdaWorkflowService workflowService, ISysHistoryService sysHistoryService){
        this.rdaStateService = rdaStateService;
        this.workflowService = workflowService;
        this.sysHistoryService = sysHistoryService;
    }

    public WorkFlowLifeCycleUtil(IRdaStateService rdaStateService,IRdaWorkflowTempleteService workflowTempleteService, ISysHistoryService sysHistoryService) {
        this.rdaStateService = rdaStateService;
        this.workflowTempleteService = workflowTempleteService;
        this.sysHistoryService = sysHistoryService;
    }

    /**文档**/
    public WorkFlowLifeCycleUtil(IRdaStateService  rdaStateService,IDynamicService dynamicService,ISysHistoryService sysHistoryService){
        this.rdaStateService = rdaStateService;
        this.dynamicService=dynamicService;
        this.sysHistoryService = sysHistoryService;
    }

    /*************************************** 历史记录写进数据库-持久化 2021-12-13 [end] **********************************************************/
    /**
     * 当前方法只针对流程对象提升/降低生命周期操作
     * @param id 当前对象Id
     * @param policyid 策略Id
     * @param event 提升/降级
     * @param moduleName 模块名称
     * @param appointTargetStateId 指定到的状态Id
     * @return 提升信息
     */
    public AjaxResult goToTargetState(Long id, Long policyid, String event, String moduleName,Long appointTargetStateId){
        if("workflow".equalsIgnoreCase(moduleName)){
            RdaWorkflow workflow = workflowService.selectRdaWorkflowById(id);
            int currentStateId = workflow.getStateid();
            System.out.println("WorkFlowLifeCycleUtil[74]:"+event+"--->>>currentStateId:" + currentStateId);
            /*获取当前策略下的所有状态**/
            Map<String, Object> eventMap = getToBeSetStateMap(policyid,currentStateId,event,appointTargetStateId);
            if ("0".equals(String.valueOf(eventMap.get("code")))) {
                int targetStateId = parseString2Int(String.valueOf(eventMap.get("targetStateId")));
                workflow.setStateid(targetStateId);
                int rows = workflowService.updateRdaWorkflow(workflow);
//                new HistoryRecordUtil(rdaStateService,sysHistoryService).lifeCycleHistory(id,currentStateId,targetStateId,event);
                return  rows > 0 ? AjaxResult.success((String) eventMap.get("msg")) : AjaxResult.error("提升失败!");
            } else if ("-1".equals(String.valueOf(eventMap.get("code")))) {
                return AjaxResult.error((String) eventMap.get("msg"));
            }else{
                return AjaxResult.error( "出现未知错误,请联系管理员!");
            }
        } else if("workflowTemplete".equalsIgnoreCase(moduleName)){
            RdaWorkflowTemplete workflow = workflowTempleteService.selectRdaWorkflowTempleteById(id);
            int currentStateId = workflow.getStateid();
            System.out.println("WorkFlowLifeCycleUtil[91]:"+event+"--->>>currentStateId:" + currentStateId);
            /*获取当前策略下的所有状态**/
            Map<String, Object> eventMap = getToBeSetStateMap(policyid,currentStateId,event,appointTargetStateId);
            if ("0".equals(String.valueOf(eventMap.get("code")))) {
                int targetStateId = parseString2Int(String.valueOf(eventMap.get("targetStateId")));
                workflow.setStateid(targetStateId);
                int rows = workflowTempleteService.updateRdaWorkflowTemplete(workflow);
//                new HistoryRecordUtil(rdaStateService,sysHistoryService).lifeCycleHistory(id,currentStateId,targetStateId,event);
                return  rows > 0 ? AjaxResult.success((String) eventMap.get("msg")) : AjaxResult.error("提升失败!");
            } else if ("-1".equals(String.valueOf(eventMap.get("code")))) {
                return AjaxResult.error((String) eventMap.get("msg"));
            }else{
                return AjaxResult.error( "出现未知错误,请联系管理员!");
            }
        } else if("document".equalsIgnoreCase(moduleName)){
            Map<String,Object> data=new HashMap<>();
            HashMap<String,Object> documentPage=dynamicService.selectDataById("rda_document",id);

            int currentStateId = (Integer)documentPage.get("stateid");

            System.out.println("WorkFlowLifeCycleUtil[108]:"+event+"--->>>currentStateId:" + currentStateId);
            /*获取当前策略下的所有状态**/
            Map<String, Object> eventMap = getToBeSetStateMap(policyid,currentStateId,event,appointTargetStateId);
            if ("0".equals(String.valueOf(eventMap.get("code")))) {

                WorkFlowLifeCycleUtil lifecycleUtil = new WorkFlowLifeCycleUtil(rdaStateService);
                int targetStateId = parseString2Int(String.valueOf(eventMap.get("targetStateId")));
                Map<Integer,Long> stateMap = lifecycleUtil.listStateOrderBySort(policyid);
                /*如果当前是非首次发布(升版后在发布),则第一版本必须废弃 2022-01-19 begin***/
                lifecycleUtil.ObsoletePreObject(id,stateMap,targetStateId,moduleName);
                /*如果当前是非首次发布(升版后在发布),则第一版本必须废弃 2022-01-19 end***/
                //如果当前被设置的节点是发布 则需要设置发布时间;必须是提升时(此时这里发布节点必须是倒数第二个  否则这里的逻辑就不适应了)
                if(targetStateId == parseLong2Int(stateMap.get(stateMap.size() -1)) && "promote".equalsIgnoreCase(event)){
                    System.out.println("WorkFlowLifeCycleUtil[120]:"+event+"--->>>targetStateId:"+targetStateId);
                    data.put("publish_time",DateUtils.getNowDate());
                }
                data.put("stateid",targetStateId);
                ArrayList<String> updateWrapper=new ArrayList<>();
                updateWrapper.add("id="+documentPage.get("id"));
                int rows =dynamicService.updateData("rda_document",data,updateWrapper);
//                new HistoryRecordUtil(rdaStateService,sysHistoryService).lifeCycleHistory(id,currentStateId,targetStateId,event);
                return  rows > 0 ? AjaxResult.success((String) eventMap.get("msg")) : AjaxResult.error("提升失败!");
            }else if ("-1".equals(String.valueOf(eventMap.get("code")))) {
                return AjaxResult.error((String) eventMap.get("msg"));
            }else{
                return AjaxResult.error( "出现未知错误,请联系管理员!");
            }
        } else {
            return AjaxResult.success(event+"对象类型不存在,请联系管理员!");
        }
    }

    /**
     * 处理当前对象是否是提升/降级
     * @param policyid 策略Id
     * @param currentStateId 当前状态Id
     * @param event 提升/降级
     * @param appointTargetStateId 指定到的状态Id
     * @return 提升/降级 后的状态Id 集合
     */
    private Map<String, Object> getToBeSetStateMap(Long policyid,int currentStateId,String event,Long appointTargetStateId){
        /*这里的sort 必须在创建状态的时候按照顺序来,即使是后面新增的状态,状态sort值也得修改 同一策略的状态sort 不能一样**/
        Long selectStateId = parseInt2Long(currentStateId);
        int currentSort = rdaStateService.selectRdaStateById(selectStateId).getSort();
        //System.out.println("LifeCycleController:promote--->>>currentSort:" + currentSort);
        /*获取当前策略下的所有状态**/
        WorkFlowLifeCycleUtil lifecycleUtil = new WorkFlowLifeCycleUtil(rdaStateService);
        return lifecycleUtil.goToAppointTargetState(policyid, event, currentSort,appointTargetStateId);
    }



    /**
     * 升级/降级到指定的状态
     * @param policyId 策略Id
     * @param event 提升/降级
     * @param currentSort 当前状态在整个策略中的索引
     * @param appointTargetStateId 指定提升或降级的状态Id 可以为空或0L
     * @return 返回成功后需要设置的状态Id 和提示信息
     */
    public Map<String,Object> goToAppointTargetState(Long policyId,String event,int currentSort,Long appointTargetStateId){
        if(appointTargetStateId == null || StringUtils.isBlank(String.valueOf(appointTargetStateId)) || appointTargetStateId == 0L){
            return goToTargetState(policyId,event,currentSort);
        } else {
            Map<String,Object> messageMap = new HashMap<>();
            WorkFlowLifeCycleUtil lifecycleUtil = new WorkFlowLifeCycleUtil(rdaStateService);
            Map<Integer,Long> stateMap = lifecycleUtil.listStateOrderBySort(policyId);

            if(stateMap.containsValue(appointTargetStateId)){
                if("promote".equalsIgnoreCase(event)){
                    /*判断当前指定节点是否为终点节点**/
                    if(stateMap.containsKey(currentSort+1)){
                        messageMap.put("code",0);
                        messageMap.put("msg","提升成功!");
                    }else{
                        messageMap.put("code",-1);
                        messageMap.put("msg","当前状态为终点状态,无法继续提升!");
                    }
                }else if("demote".equalsIgnoreCase(event)){
                    /*判断当前指定节点是否为初始节点**/
                    if(stateMap.containsKey(currentSort-1)){
                        messageMap.put("code",0);
                        messageMap.put("msg","降级成功!");
                    }else{
                        messageMap.put("code",-1);
                        messageMap.put("msg","当前状态为初始状态,无法继续降级!");
                    }
                }
            }else{
                messageMap.put("code",-1);
                messageMap.put("msg","指定状态和策略不匹配,无法操作!");
            }
            messageMap.put("targetStateId",appointTargetStateId);
            return messageMap;
        }
    }

    /**
     * 根据当前策略 自动升级及降级
     * @param policyId 策略id
     * @param event 事件(升级或降级)
     * @param currentSort 当前对象的状态对应的sort值
     * @return 返回成功后需要设置的状态Id 和提示信息
     */
    private Map<String,Object> goToTargetState(Long policyId,String event,int currentSort){
        Map<String,Object> messageMap = new HashMap<>();
        WorkFlowLifeCycleUtil lifecycleUtil = new WorkFlowLifeCycleUtil(rdaStateService);
        Map<Integer,Long> stateMap = lifecycleUtil.listStateOrderBySort(policyId);
        Long targetStateId = -1L;
        if("promote".equalsIgnoreCase(event)){
            if(stateMap.containsKey(currentSort+1)){
                targetStateId = stateMap.get(currentSort+1);
                messageMap.put("code",0);
                messageMap.put("msg","提升成功!");
            }else{
                messageMap.put("code",-1);
                messageMap.put("msg","当前状态为终点状态,无法继续提升!");
            }
            messageMap.put("targetStateId",targetStateId);
        }  else if("demote".equalsIgnoreCase(event)){
            if(stateMap.containsKey(currentSort-1)){
                targetStateId = stateMap.get(currentSort-1);
                messageMap.put("code",0);
                messageMap.put("msg","降级成功!");
            }else{
                messageMap.put("code",-1);
                messageMap.put("msg","当前状态为初始状态,无法继续降级!");
            }
            messageMap.put("targetStateId",targetStateId);
        }
        return messageMap;
    }

    /**
     * 根据当前策略Id 查询所有的状态 并排序
     * @param policyId 策略id
     * @return 返回根据sort 排好序的状态Map
     */
    public Map<Integer,Long> listStateOrderBySort(Long policyId){
        List<RdaState> stateList = rdaStateService.getStatesByPolicyId(policyId);
        Map<Integer,Long> sortedStateMap = new TreeMap<>(new Comparator<Integer>() {
            @Override
            public int compare(Integer o1, Integer o2) {
                return o1 - o2 ;
            }
        });
        /*将查询到的State 按照sort 排序**/
        for(RdaState state : stateList){
            sortedStateMap.put(state.getSort(),state.getId());
        }
        return sortedStateMap;
    }

    private Long parseInt2Long(int stateId){
        return Long.parseLong(String.valueOf(stateId));
    }

    private Integer parseString2Int(String stateId){
        return Integer.parseInt(stateId);
    }

    private Integer parseLong2Int(Long stateId){return Integer.parseInt(String.valueOf(stateId));
    }

    /**
     * 针对非首版对象发布时,将上一版本对象的状态设置为废弃
     * 仅限提升时
     * @param id 当前升版对象的Id
     * @param stateMap 状态Map
     * @param targetStateId 目标状态
     * @param moduleName 当前模块名称
     */
    public void ObsoletePreObject(Long id,Map<Integer,Long> stateMap,int targetStateId,String moduleName){
        //这里发布节点必须是倒数第二个  否则这里的逻辑就不适应了
        if(targetStateId == parseLong2Int(stateMap.get(stateMap.size() -1))){
            if("document".equalsIgnoreCase(moduleName)){
                /*如果是升版后的对象 此时recordId 必然会是上一版本的对象Id;如果是首版 则recordId 为空**/
                HashMap<String,Object> documentPage=dynamicService.selectDataById("rda_document",id);
                Long recordId =(Long)documentPage.get("recordid");
                System.out.println("LifecycleUtil:ObsoletePreObject--->>>recordId = " + recordId);
                if(!"null".equals(String.valueOf(recordId)) && String.valueOf(recordId) != null && !"".equals(String.valueOf(recordId))){
                    HashMap<String,Object> documentPage2=dynamicService.selectDataById("rda_document",recordId);
                    Long docId=(Long)documentPage2.get("id");
                    Map<String, Object> data=new HashMap<>();
                    data.put("stateid",parseLong2Int(stateMap.get(stateMap.size())));
                    ArrayList<String> updateWrapper=new ArrayList<>();
                    updateWrapper.add("id="+docId);
                    dynamicService.updateData("rda_document",data,updateWrapper);
                }

            }
        }
    }

}
